package game

import (
	"fmt"
	"github.com/robfig/cron/v3"
	"server/MergeConst"
	"server/db"
	"server/msg"
	"sort"
	"time"

	"google.golang.org/protobuf/proto"
)

type PlayerEmailData struct {
	*PlayerData
	Data       msg.ResBriefEmailData
	SqlStructs []db.SqlEmailStruct
	ZeroCronID cron.EntryID
	WeekCronID cron.EntryID
	Mcron      *cron.Cron
}

func (p *PlayerEmailData) LoadDataFromDB(dwUin interface{}) bool {

	sqlStr := "SELECT * FROM system_mail_info WHERE dwUin = ?"
	if err := db.SqlDb.Select(&p.SqlStructs, sqlStr, dwUin.(int32)); err != nil {
		fmt.Printf("get data failed, err:%v\n", err)
		p.IsHaveDataDb = false
	} else {
		p.IsHaveDataDb = true
	}

	CurTime := int32(time.Now().Unix())

	deleteList := []int{}
	deleteDbList := []int32{}
	for i := 0; i < len(p.SqlStructs); i++ {
		item := p.SqlStructs[i]
		if item.RecvTime > 0 && item.Status == 1 && CurTime-item.RecvTime >= MergeConst.G_Clear_Read_Email_Limit {
			deleteList = append(deleteList, i)
			deleteDbList = append(deleteDbList, item.EmailId)
		}
	}
	tempList := []db.SqlEmailStruct{}
	startIndex := 0
	for i := 0; i < len(deleteList); i++ {
		curIndex := deleteList[i]
		if curIndex == startIndex {
			startIndex = startIndex + 1
			continue
		}
		tempList = append(tempList, p.SqlStructs[startIndex:curIndex]...)
		startIndex = curIndex + 1
	}
	if startIndex <= len(p.SqlStructs)-1 {
		tempList = append(tempList, p.SqlStructs[startIndex:]...)
	}
	p.SqlStructs = tempList
	p.DeleteOutlineMail(deleteDbList)

	sort.Slice(p.SqlStructs, func(i, j int) bool {
		if p.SqlStructs[i].Status == p.SqlStructs[j].Status {
			if p.SqlStructs[i].Type == p.SqlStructs[j].Type {
				return p.SqlStructs[i].SendTime > p.SqlStructs[j].SendTime
			} else {
				return p.SqlStructs[i].Type > p.SqlStructs[j].Type
			}

		} else {
			return p.SqlStructs[i].Status < p.SqlStructs[j].Status
		}
	})

	for i := 0; i < len(p.SqlStructs); i++ {
		item := p.SqlStructs[i]
		if item.Status == 0 {
			p.SqlStructs[i].Status = 1
			db.FormatAllMemUpdateDb(&p.SqlStructs[i], "system_mail_info", "mail_id")
		}
	}

	p.Mcron = cron.New()
	p.Reconnect(false)

	return true
}
func (p *PlayerEmailData) Reconnect(b bool) {
	p.ZeroCronID, _ = p.Mcron.AddFunc("@every 5s", func() {
		p.IntervalGetUnsendMails()
	})
	p.Mcron.Start()
}
func (p *PlayerEmailData) DeleteOutlineMail(deleteList []int32) {
	sqlStr := "DELETE FROM system_mail_info WHERE mail_id = ?"
	for i := 0; i < len(deleteList); i++ {

		result, err := db.SqlDb.Exec(sqlStr, deleteList[i])
		if err != nil {
			fmt.Printf("exec failed, err:%v\n", err)
			return
		}
		affectedRows, err := result.RowsAffected()
		if err != nil {
			fmt.Printf("get affected failed, err:%v\n", err)
			return
		}
		fmt.Printf("delete data success, affected rows:%d\n", affectedRows)
	}
}

func (p *PlayerEmailData) IntervalGetUnsendMails() {
	sqlStr := "SELECT * FROM system_mail_info WHERE dwUin = ? AND state = ?"
	SqlStructs := []db.SqlEmailStruct{}
	if err := db.SqlDb.Select(&SqlStructs, sqlStr, p.M_Player.M_DwUin, 0); err != nil {

	} else {
		for i := 0; i < len(SqlStructs); i++ {
			SqlStructs[i].Status = 1
			db.FormatAllMemUpdateDb(&SqlStructs[i], "system_mail_info", "mail_id")
		}
		if len(SqlStructs) > 0 {
			p.NotifyNewBriefEmailData(SqlStructs)
		}

	}
}

func (p *PlayerEmailData) NotifyNewBriefEmailData(SqlStructs []db.SqlEmailStruct) {
	notify := &msg.NotifyNewBriefEmailData{}
	notify.DwUin = p.M_Player.M_DwUin
	notify.MEmailList = []*msg.BriefEmailStruct{}

	p.SqlStructs = append(p.SqlStructs, SqlStructs...)

	for i := 0; i < len(SqlStructs); i++ {
		st := &msg.BriefEmailStruct{}
		st.EmailId = SqlStructs[i].EmailId
		st.Sender = SqlStructs[i].Sender
		st.Title = SqlStructs[i].Title
		st.CurrencyCount = SqlStructs[i].CurrencyCount
		st.CurrencyInfo = SqlStructs[i].CurrencyInfo
		st.ItemCount = SqlStructs[i].ItemCount
		st.ItemInfo = SqlStructs[i].ItemInfo
		st.SendTime = SqlStructs[i].SendTime
		st.Status = 1
		st.Type = SqlStructs[i].Type
		SqlStructs[i].Status = 1
		notify.MEmailList = append(notify.MEmailList, st)
	}
	agent := p.GetPlayer().GetAgentByPlayer()
	data, _ := proto.Marshal(notify)
	G_getGameLogic().PackResInfo(agent, "NotifyNewBriefEmailData", data)
}

func (p *PlayerEmailData) ResBriefEmailData() {
	res := &msg.ResBriefEmailData{}
	res.DwUin = p.M_Player.M_DwUin
	res.MEmailList = []*msg.BriefEmailStruct{}
	for i := 0; i < len(p.SqlStructs); i++ {
		st := &msg.BriefEmailStruct{}
		st.EmailId = p.SqlStructs[i].EmailId
		st.Sender = p.SqlStructs[i].Sender
		st.Title = p.SqlStructs[i].Title
		st.CurrencyCount = p.SqlStructs[i].CurrencyCount
		st.CurrencyInfo = p.SqlStructs[i].CurrencyInfo
		st.ItemCount = p.SqlStructs[i].ItemCount
		st.ItemInfo = p.SqlStructs[i].ItemInfo
		st.SendTime = p.SqlStructs[i].SendTime
		st.Status = p.SqlStructs[i].Status
		st.Type = p.SqlStructs[i].Type
		res.MEmailList = append(res.MEmailList, st)
	}

	agent := p.GetPlayer().GetAgentByPlayer()
	data, _ := proto.Marshal(res)
	G_getGameLogic().PackResInfo(agent, "ResBriefEmailData", data)
}

func (p *PlayerEmailData) FindSqlStructByMailId(mailId int32) *db.SqlEmailStruct {
	for i := 0; i < len(p.SqlStructs); i++ {
		if p.SqlStructs[i].EmailId == mailId {
			return &p.SqlStructs[i]
		}
	}
	return nil
}

func (p *PlayerEmailData) DeleteSqlStructByMailId(mailId int32) *db.SqlEmailStruct {
	var temp *db.SqlEmailStruct = nil
	var list []db.SqlEmailStruct
	for i := 0; i < len(p.SqlStructs); i++ {
		if p.SqlStructs[i].EmailId == mailId {
			temp = &p.SqlStructs[i]
			if i > 0 {
				list = append(list, p.SqlStructs[:i]...)
			}
			if i < len(p.SqlStructs)-1 {
				list = append(list, p.SqlStructs[i+1:]...)
			}
			break
		}
	}
	p.SqlStructs = list

	return temp
}

func (p *PlayerEmailData) ResDetailEmailData(buf []byte) {
	res := &msg.ResDetailEmailData{}
	req := &msg.ReqDetailEmailData{}
	proto.Unmarshal(buf, req)

	st := p.FindSqlStructByMailId(req.EmailId)
	if st != nil {
		res.ResultCode = 0
		res.Content = st.Content
		res.EmailId = req.EmailId
		res.RewardType = st.RewardType
		res.RewardId = st.RewardId
		res.RewardCount = st.RewardCount
		res.LinkUrl = st.LinkUrl
		if st.Type == 0 {
			st.Status = 2
			st.RecvTime = int32(time.Now().Unix())
			db.FormatAllMemUpdateDb(st, "system_mail_info", "mail_id")
		}

	} else {
		res.ResultCode = MergeConst.Protocol_Email_Find_Fail
	}
	agent := p.GetPlayer().GetAgentByPlayer()
	data, _ := proto.Marshal(res)
	G_getGameLogic().PackResInfo(agent, "ResDetailEmailData", data)
}
func (p *PlayerEmailData) ResDeleteEmail(buf []byte) {
	res := &msg.ResDeleteEmail{}
	req := &msg.ReqDeleteEmail{}
	proto.Unmarshal(buf, req)

	if p.DeleteSqlStructByMailId(req.EmailId) != nil {
		res.EmailId = req.EmailId
		res.ResultCode = 0
		deleteList := []int32{req.EmailId}
		p.DeleteOutlineMail(deleteList)

	} else {
		res.ResultCode = MergeConst.Protocol_Email_Find_Fail
	}
	agent := p.GetPlayer().GetAgentByPlayer()
	data, _ := proto.Marshal(res)
	G_getGameLogic().PackResInfo(agent, "ResDeleteEmail", data)
}

func (p *PlayerEmailData) ResGetEmailReward(buf []byte) {
	res := &msg.ResGetEmailReward{}
	req := &msg.ReqGetEmailReward{}
	proto.Unmarshal(buf, req)

	st := p.FindSqlStructByMailId(req.EmailId)
	if st != nil {
		res.ResultCode = 0
		res.EmailId = req.EmailId
		res.RewardType = st.RewardType
		res.RewardId = st.RewardId
		res.RewardCount = st.RewardCount
		st.Status = 2
		st.RecvTime = int32(time.Now().Unix())
		db.FormatAllMemUpdateDb(st, "system_mail_info", "mail_id")
		///发送奖励
	} else {
		res.ResultCode = MergeConst.Protocol_Email_Find_Fail
	}
	agent := p.GetPlayer().GetAgentByPlayer()
	data, _ := proto.Marshal(res)
	G_getGameLogic().PackResInfo(agent, "ResGetEmailReward", data)
}
func (p *PlayerEmailData) ClearData() bool {
	p.SaveDataFromDB("")
	p.Mcron.Remove(p.ZeroCronID)
	p.Mcron.Stop()
	return true
}
